home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / tcp_ip / wnos / wn941101 / alloc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-10  |  27.8 KB  |  899 lines

  1. /*======================================================================
  2. *  File Name:  alloc.c                                                  *
  3. *  Purpose  :  memory allocation routines                               *
  4. * Allocation routines. changed from K&R to the use of TURBO C++ offered *
  5. * routines. This is probably not a very portable solution, but it gives *
  6. * at least some relief when used under (MS)DOS.                         *
  7. *                                                                       *
  8. *  Date          Name         Description                               *
  9. *  ----          ----         -----------                               *
  10. *  04-apr-1991   AA6HM/DK5DC  initial implementation                    *
  11. *  09-apr-1991   AA6HM/DK5DC  added memory record                       *
  12. *  11-apr-1991   AA6HM/DK5DC  added crashdump facility                  *
  13. *  14-apr-1991   AA6HM/DK5DC  changed crashdump to ask Turbo C++ via    *
  14. *                             heapchecknode(),if he agrrees to dump and *
  15. *                             exit because of a corrupted node          *
  16. *=======================================================================*/
  17. #define __ALLOC_C 1
  18.  
  19. #include <stdio.h>
  20. #include <dos.h>
  21. #include <alloc.h>
  22. #include <fcntl.h>                      /* for filemodes DK5DC          */
  23. #include <io.h>                         /* for creattemp()              */
  24. #include <ctype.h>                                              /* for isprint                                  */
  25. #include <conio.h>
  26. #include "global.h"
  27. #include "proc.h"
  28. #include "cmdparse.h"
  29. #include "mbuf.h"
  30. #include "session.h"
  31. #include "files.h"
  32. #include "commands.h"                                   /* for doexit()                                 */
  33.  
  34. #ifdef __CPLUSPLUS
  35. #define Free 0
  36. #define Used 1
  37. #define Over 2
  38. #endif
  39. #define MDDEBUG
  40.  
  41. static unsigned long Intalloc;   /* Calls to malloc with ints disabled  */
  42. static unsigned long Memfail;    /* Count of allocation failures        */
  43. static unsigned long Allocs;     /* Total allocations                   */
  44. static unsigned long Frees;      /* Total frees                         */
  45. static unsigned long Invalid;    /* Total calls to free with garbage arg*/
  46. static unsigned long Intfree;    /* Calls to free with ints disabled    */
  47. static unsigned long Overuse;    /* tot calls to free with overused arg */
  48.  
  49. static int Memwait = 0;          /* Number of tasks waiting for memory  */
  50. static int Memcold = 0;          /* controls rebooting when memory goes low */
  51.  
  52. #ifdef MDEBUG
  53. static unsigned long Sizes[16];
  54. static FILE *rfp = 0;            /* points to memrecord                 */
  55. static int rflag = 0;
  56. #endif
  57. extern int Nibufs;
  58. extern unsigned Ibufsize;
  59. extern int setuns __ARGS((unsigned *var,char *label,int argc,char *argv[]));
  60.  
  61.  
  62. #ifdef MDEBUG
  63. #  define PARA 16
  64. #  define UNIT 8
  65. #  define ALLOC "\xAA"           /* marker for alloc                    */
  66. #  define FREE  "\x55"           /* marker for free                     */
  67.  
  68. /*----------------------------------------------------------------------*
  69. * template to access inserted debug info                                *
  70. *-----------------------------------------------------------------------*/
  71. typedef struct {
  72.    unsigned line;
  73.    char file[10];
  74. }Hd;
  75.  
  76. #else
  77.  
  78. /*----------------------------------------------------------------------*
  79. * template to access Turbo C++'s memory linkages
  80. *-----------------------------------------------------------------------*/
  81. typedef struct   {
  82.    unsigned np;                  /* noOfParagraphs in block             */
  83.    unsigned seg;                 /* used: link to previous segment      */
  84.    unsigned backseg,forseg;      /* free freelist linkage               */
  85. }Id;
  86.  
  87. #define Hd char
  88. #endif
  89.  
  90. /*----------------------------------------------------------------------*
  91. * the two variables below are maintained by C++ to mark the start and   *
  92. * end of the used heap                                                  *
  93. *-----------------------------------------------------------------------*/
  94. #ifdef __CPLUSPLUS
  95. extern unsigned far __first;
  96. extern unsigned far __last;
  97. extern unsigned far __rover;
  98. // DL8YQ
  99. static Hd huge * near checkheap __ARGS((void));
  100. #endif
  101.  
  102. #ifdef MDEBUG
  103. static int dump(Hd huge *cret);
  104. #endif
  105. /*-----------------------------------------------------------------------*
  106. * Set the C++ roving memory pointer to the first free block              *
  107. *------------------------------------------------------------------------*/
  108. static void near
  109. _setrover (void)
  110. {
  111. struct heapinfo hp;
  112.  
  113.        hp.ptr = 0;
  114.        while(heapwalk(&hp) != _HEAPEND) {
  115.                            if(hp.in_use == 0){
  116.                                         __rover = FP_SEG(hp.ptr);
  117.                                         break;
  118.                            }
  119.        }
  120. }
  121.  
  122. /*----------------------------------------------------------------------*
  123. * Allocate block of 'nb' bytes                                          *
  124. *-----------------------------------------------------------------------*/
  125. #ifdef MDEBUG
  126. void *
  127. mxalloc(char *file,unsigned line,unsigned nb)
  128. #else
  129. void *
  130. mxalloc(unsigned nb)
  131. #endif
  132. {
  133. register Hd *node;
  134.  
  135.  
  136. #ifdef MDEBUG
  137. unsigned foo;
  138. int i;
  139. struct time stime;
  140. #endif
  141.  
  142.    if(!istate())
  143.           Intalloc++;
  144.    /*-------------------------------------------------------------------*
  145.    * If memory is below Memthresh, reboot the system. This seemes to be *
  146.    * a more secure way to prevent garbage and 'unexpected modes'.       *
  147.    *--------------------------------------------------------------------*/
  148.    if((availmem() < (Memthresh + nb))) { /* !! TEST !! */
  149.           if(Memcold) {
  150.                 void (*foo) __ARGS((void));
  151.  
  152.         foo = MK_FP(0xffff,0);  /* FFFF:0000 is hardware reset vector */
  153.                 (*foo)();               /* no return */
  154.           } else {
  155.         doexit(252,0,0);
  156.           }
  157.    }
  158.    if(nb == 0)
  159.       return NULL;
  160.  
  161.       _setrover();
  162. #ifdef MDEBUG
  163.    /*-------------------------------------------------------------------*
  164.    * Record the size of this request                                    *
  165.    *--------------------------------------------------------------------*/
  166.    foo = nb;
  167.    for(i=0;i<16;i++){
  168.           if(foo >= 32768L)
  169.                  break;
  170.           foo <<= 1;
  171.    }
  172.    Sizes[15-i]++;
  173.  
  174.    /*-------------------------------------------------------------------*
  175.    * the calloc() is merely a circumvention, cause I'm unable to find   *
  176.    * ALL the uninitialized 'next ptr's' in that whole crop of NOS       *
  177.    * functions. calloc() makes sure to get (zero) initialized memory    *
  178.    *--------------------------------------------------------------------*/
  179. #ifdef LARGEDATA
  180.    if ((node = farcalloc(1,nb+PARA))!=0) {
  181. #else
  182.    if ((node = calloc(1,nb+PARA))!=0) {
  183. #endif
  184.           /*----------------------------------------------------------------*
  185.           * insert the line/file info passed when MDEBUG is on              *
  186.       *-----------------------------------------------------------------*/
  187.           sprintf(node->file,"%.8s",file);
  188.           node->line = line;
  189.           /*----------------------------------------------------------------*
  190.           * if recording is on, build a record and write it into the file   *
  191.           *-----------------------------------------------------------------*/
  192.           if (rflag)   {
  193.                  /*-------------------------------------------------------------*
  194.                  * use dostime(), cause it calculates much faster than time()   *
  195.                  * and has a granularity of 10 milliseconds                     *
  196.          *--------------------------------------------------------------*/
  197.                  unsigned seg;
  198.                  gettime(&stime);
  199.                  fwrite(ALLOC,1,1,rfp);         /* write the marker             */
  200.          fwrite(&stime,sizeof(struct time),1,rfp);
  201.                  seg = FP_SEG((char *)node-4);  /* alloce'd segment             */
  202.                  fwrite(&seg,sizeof(unsigned),1,rfp);
  203.          fwrite(((char *)node-4),PARA,1,rfp);
  204.                  seg = line;
  205.                  fwrite(&seg,sizeof(unsigned),1,rfp);
  206.          fwrite(file,10,1,rfp);
  207.           }
  208.           Allocs++;
  209.           return(node+1);
  210.    }
  211. #else
  212. #ifdef LARGEDATA
  213.    if ((node = farcalloc(1,nb)) != 0) {
  214. #else
  215.    if ((node = calloc(1,nb)) != 0) {
  216. #endif
  217.           Allocs++;
  218.           return(node);
  219.    }
  220. #endif
  221.  
  222.    Memfail++;
  223.    return(NULL);
  224. }
  225.  
  226. /*----------------------------------------------------------------------*
  227. * Put memory block back on heap                                         *
  228. *-----------------------------------------------------------------------*/
  229. #ifdef MDEBUG
  230. void
  231. xfree(char *file,unsigned line,void *b)
  232. #else
  233. void
  234. xfree(void *b)
  235. #endif
  236. {
  237. #ifdef __CPLUSPLUS
  238. Hd huge *cret;
  239. #endif
  240. #ifdef MDEBUG
  241. Hd huge *blk;
  242. struct time stime;
  243. #endif
  244.  
  245.    if(b == NULL)
  246.       return;                           /* Required by ANSI             */
  247.  
  248.    if(!istate())
  249.       Intfree++;
  250.  
  251. #ifdef MDEBUG
  252.    blk = (Hd *)b - 1;
  253. #endif
  254. #ifdef __CPLUSPLUS
  255.    /*-------------------------------------------------------------------*
  256.    * make the audit check
  257.    *--------------------------------------------------------------------*/
  258.    if((cret = checkheap()) != 0) {
  259. #ifdef MDEBUG
  260.       tprintf("free: WARNING! corrupted Node (%Fp) %10.10s %05u proc %s\n",
  261.         cret,cret->file,cret->line,Curproc->name);
  262.       dump(cret);                       /* POOF!!!!!                    */
  263. #else
  264.       printf("\nfree(): corrupted Node (%Fp) proc %s\n\n",
  265.         cret,Curproc->name);
  266. #endif
  267.       exit(255);
  268.    }
  269. #endif
  270. #ifdef MDEBUG
  271.      else if (rflag)   {
  272.       unsigned seg;
  273.       gettime(&stime);
  274.       fwrite(FREE,1,1,rfp);
  275.       fwrite(&stime,sizeof(struct time),1,rfp);
  276.       seg = FP_SEG((char *)blk-4);
  277.       fwrite(&seg,sizeof(unsigned),1,rfp);
  278.       fwrite(((char *)blk-4),PARA,1,rfp);
  279.    }
  280. #endif
  281.  
  282. #ifdef MDEBUG
  283.    free((void *)blk);
  284. #else
  285.    free((void *)b);
  286. #endif
  287.    Frees++;
  288.  
  289.    if(Memwait != 0)
  290.       psignal(&Memwait,0);
  291.  
  292. }
  293.  
  294. #ifdef MDEBUG
  295. /*----------------------------------------------------------------------*
  296. * Dump the memory in case of an error detected by checkheap and exit..  *
  297. * low level routines are used.....                                      *
  298. *-----------------------------------------------------------------------*/
  299. static int
  300. dump(Hd huge *cret)
  301. {
  302. int fd,seg,fmode;
  303. char huge *para;
  304. extern struct proc *Curproc;            /* Currently running process    */
  305. extern struct proc *Rdytab;             /* Processes ready to run (not including curproc)*/
  306. extern struct proc *Waittab[];          /* Waiting process list         */
  307. extern struct proc *Susptab;            /* Suspended processes          */
  308. extern struct timer *Timers;
  309. struct timer *tp;
  310. int i_state;
  311. char path[128];
  312.  
  313.    if(getenv("HOME") != NULL) {
  314.       strcpy(path,getenv("HOME"));
  315.       strcat(path,"\\");
  316.    } else
  317.       strcpy(path,"\\");
  318.  
  319.    fmode = _fmode;                      /* preserve filemode            */
  320.    _fmode = O_BINARY;
  321.  
  322.    if ((fd = creattemp(path,0))<0)   {
  323.       _fmode = fmode;
  324.       return(-1);
  325.    } else {
  326.       i_state = dirps();
  327.       tprintf("Memory dump started...file = %s\n",path);
  328.       write(fd,&__first,2);             /* write __first ptr            */
  329.       write(fd,&__last,2);              /* write __last ptr             */
  330.       write(fd,&cret,4);                /* save error position          */
  331.       write(fd,(char *)cret-4,16);      /* save suspected header        */
  332.       /*----------------------------------------------------------------*
  333.       * save processing queue ptrs...                                   *
  334.       *-----------------------------------------------------------------*/
  335.       write(fd,&Curproc,sizeof(struct proc *));
  336.       write(fd,&Rdytab,sizeof(struct proc *));
  337.       write(fd,&Susptab,sizeof(struct proc *));
  338.       write(fd,&Waittab,16*sizeof(struct proc *));
  339.       /*----------------------------------------------------------------*
  340.       * save the Timerchain.....                                        *
  341.       *-----------------------------------------------------------------*/
  342.       for (tp = Timers; tp; tp = tp->next)
  343.          write(fd,tp,sizeof(struct timer ));
  344.       /*----------------------------------------------------------------*
  345.       * save session control blocks                                     *
  346.       *-----------------------------------------------------------------*/
  347.       seg = NSESSIONS;
  348.       write(fd,&seg,sizeof(int));
  349.       write(fd,Sessions,sizeof(struct session)*Nsessions);
  350.       /*----------------------------------------------------------------*
  351.       * save the file descriptors, at least the first 16...             *
  352.       *-----------------------------------------------------------------*/
  353.       write(fd,(char *)&_streams,16*sizeof(FILE));
  354.       /*----------------------------------------------------------------*
  355.       * now dump the whole heap... maybe expanded to whole system       *
  356.       * sessions,tcb's etc  to get a snapshot of the system             *
  357.       *-----------------------------------------------------------------*/
  358.       for (seg = __first; seg < __last; seg++)   {
  359.          para = MK_FP(seg,0);
  360.          write(fd,(void *)para,PARA);
  361.       }
  362.       close(fd);
  363.    }
  364.    restore(i_state);
  365.    _fmode = fmode;
  366.    return(0);
  367. }
  368. #endif
  369.  
  370. /*----------------------------------------------------------------------*
  371. * This is a very rough check routine. As I dive into the code           *
  372. * the routine might be streamlined  DK5DC                               *
  373. * As far as I could find the facts, the C++ memory links are built as   *
  374. * follows:                                                              *
  375. *      1.  Memory is ALWAYS allocated on a paragraph (16 Byte) Basis    *
  376. *          TC++ ALWAYS returns a address in the form                    *
  377. *          Segment:0004. The first four bytes in the first paragraph are*
  378. *          used for size and link informations. The first two bytes     *
  379. *          contain the size of the block in paragraphs                  *
  380. *          The remaining two bytes contain a segment address pointing   *
  381. *          to the previous (allocated block) or to (^self).             *
  382. *      2.  A FREE entry uses two more byte pairs for header information *
  383. *           (This caused some bad NOS crashes when some code was running*
  384. *            along a linked list, a block was freed, the 'next'pointer  *
  385. *            was defined as the first member of the structure and NOS   *
  386. *            tried to access that ptr AFTER freeing the block)          *
  387. *          Anyway, those two pairs of code contain a backward           *
  388. *          and forward pointer to its free neighbours.                  *
  389. *-----------------------------------------------------------------------*/
  390. #ifdef __CPLUSPLUS
  391. static Hd huge * near
  392. checkheap(void)
  393. {
  394. unsigned prev;
  395. unsigned last;
  396. unsigned run;
  397. Id huge *rp;
  398.  
  399.    last =__last;
  400.    run = prev =__first;
  401.    rp = 0;
  402.    /*-------------------------------------------------------------------*
  403.    * scan the heap                                                      *
  404.    *--------------------------------------------------------------------*/
  405.    while (run<last)   {
  406.           rp = MK_FP(run,0);
  407.           /*----------------------------------------------------------------*
  408.           * make the test                                                   *
  409.           *-----------------------------------------------------------------*/
  410.           if (rp->seg != NULL && rp->seg != prev)   {
  411.                  rp = MK_FP(run,4);
  412.                  /*-------------------------------------------------------------*
  413.                  * before getting nasty, ask C++ to check again...              *
  414.                  *--------------------------------------------------------------*/
  415.                  if(heapcheck() < 0) {
  416.                         rp = MK_FP(prev,0);
  417.                         return((Hd huge *)((char *)rp+4));
  418.                  }
  419.           }
  420.           prev = run;
  421.           run += rp->np;
  422.    }
  423.    return(0);
  424. }
  425. #endif
  426.  
  427. /* new DL8YQ */
  428. /*----------------------------------------------------------------------*
  429. * Version of malloc() that waits if necessary for memory to become available *
  430. *-----------------------------------------------------------------------*/
  431. #ifdef MDEBUG
  432. void *
  433. mxallocw(char *file,unsigned line,unsigned nb)
  434. #else
  435. void *
  436. mxallocw(unsigned nb)
  437. #endif
  438. {
  439.         register char *cp;
  440.  
  441.         semwait(&Memwait,1);
  442.         cp=mxalloc(nb);
  443.         semrel(&Memwait);
  444.     return cp;
  445.  /*
  446.         while ((cp = mxalloc(nb)) == NULL){
  447.             Memwait++;
  448.             pwait(&Memwait);
  449.             Memwait--;
  450.         }
  451.         return cp;
  452. */
  453. }
  454.  
  455.  
  456. /*----------------------------------------------------------------------*
  457. * Allocate block of cleared memory                                      *
  458. *-----------------------------------------------------------------------*/
  459. #ifdef MDEBUG
  460.  
  461. void *
  462. cxalloc(char *file,unsigned line,unsigned nelem,unsigned size)
  463. #else
  464. void *
  465. cxalloc(unsigned nelem,unsigned size)
  466. #endif
  467. {
  468. #ifdef MDEBUG
  469.     char *cp = mxalloc(file,line,(nelem * size));
  470. #else
  471.     register char *cp =  calloc(1,nelem * size);
  472. #endif
  473.  
  474.    return cp;
  475. }
  476.  
  477. /*----------------------------------------------------------------------*
  478. * Version of calloc that waits if necessary for memory to become available *
  479. *-----------------------------------------------------------------------*/
  480. #ifdef MDEBUG
  481. void *
  482. cxallocw(char *file,unsigned line,unsigned nelem,unsigned size)
  483. #else
  484. void *
  485. cxallocw(unsigned nelem,unsigned size)
  486. #endif
  487. {
  488.         register char *cp;
  489.  
  490.     semwait(&Memwait,1);
  491.     cp = mxalloc(nelem * size);
  492.     semrel(&Memwait);
  493.     return cp;
  494. }
  495.  
  496. /*----------------------------------------------------------------------*
  497. * Copy a string to a malloc'ed buffer. Turbo C has this one in its      *
  498. * library, but it doesn't call mallocw() and can therefore return NULL. *
  499. * NOS uses of strdup() generally don't check for NULL, so they need this*
  500. * one.                                                                  *
  501. *                                                                       *
  502. * Changed the name to strxdup and added the file/line pair insertion.   *
  503. * Otherwise only the malloc() would be recorded, which is always inside *
  504. * strxdup() and not the strdup location itself.                         *
  505. *-----------------------------------------------------------------------*/
  506. #ifdef MDEBUG
  507. char *
  508. strxdup(char *file,unsigned line,const char *s)
  509. #else
  510. char *
  511. strxdup(const char *s)
  512. #endif
  513. {
  514. char *out;
  515. int len;
  516.  
  517.    if(s == NULLCHAR)
  518.           return NULLCHAR;
  519.  
  520.    len = strlen(s);
  521. #ifdef MDEBUG
  522.    out = mxallocw(file,line,len+1);
  523. #else
  524.    out = mxallocw(len+1);
  525. #endif
  526.    /* This is probably a tad faster than strcpy, since we know the len */
  527.    memcpy(out,s,len);
  528.    out[len] = '\0';
  529.    return out;
  530. }
  531.  
  532. /*----------------------------------------------------------------------*
  533. * Return available memory on our heap plus available system memory      *
  534. *-----------------------------------------------------------------------*/
  535.  unsigned long availmem()
  536. {
  537.         return  (unsigned long)coreleft();
  538. }
  539.  
  540. /*----------------------------------------------------------------------*
  541. *-----------------------------------------------------------------------*/
  542. #ifdef MDEBUG
  543. int
  544. openmemrec(char *name)
  545. {
  546.    if ((rfp = fopen(name,"w+b",0,1)) == NULLFILE) {
  547.           tprintf("Error opening file: %s\n",name);
  548.           return(-1);
  549.    }
  550.    fprintf(rfp,
  551.           "THIS FILE CONTAINS BINARY DATA... use ANALMEM                \n\r\x1a");
  552.    tprintf("Recording memory allocs to %s\n",name);
  553.    rflag = 1;
  554.    return(0);
  555. }
  556. #endif
  557.  
  558. #ifdef MDEBUG
  559. static void * near
  560. sltop(long l)
  561. {
  562.    return(MK_FP(l,16));
  563. }
  564. #endif
  565.  
  566. #ifdef MDEBUG
  567. /* Convert byte to two ascii-hex characters */
  568. static void near
  569. ctohex(char *buf,int16 c)
  570. {
  571.    static char hex[] = "0123456789abcdef";
  572.  
  573.    *buf++ = hex[hinibble(c)];
  574.    *buf = hex[lonibble(c)];
  575. }
  576. #endif
  577.  
  578. #ifdef MDEBUG
  579. /* Print a buffer up to 16 bytes long in formatted hex with ascii
  580.  * translation, e.g.,
  581.  * 0000: 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f  0123456789:;<=>?
  582.  */
  583. static void near
  584. fmtline(FILE *fp,int16 addr,char *buf,int16 len,int type)
  585. {
  586. char line[81], *aptr, *cptr, c;
  587.  
  588.    memset(line,' ',sizeof(line));
  589.    ctohex(line,(int16)hibyte(addr));
  590.    ctohex(line+2,(int16)lobyte(addr));
  591.    aptr = &line[6];
  592.    cptr = &line[55];
  593.    while(len-- != 0){
  594.           c = *buf++;
  595.           ctohex(aptr,(int16)uchar(c));
  596.           aptr += 3;
  597.           c &= 0x7f;
  598.           *cptr++ = isprint(uchar(c)) ? c : '.';
  599.    }
  600.    *cptr++ = '\0';
  601.    if (type)
  602.           fprintf(fp,"%s\n\r",line);
  603.    else
  604.       tprintf("%s\n",line);
  605.    if (fp)
  606.       fwrite(line,1,(unsigned)(cptr-line),fp);
  607. }
  608. #endif
  609.  
  610. #ifdef __CPLUSPLUS
  611. static int near
  612. _checkok(void)
  613. {
  614.    if (heapcheck() != _HEAPOK) {
  615.           tputs("Heap doesn't check ok, trying to find failing node\n");
  616.       return(0);
  617.    }
  618.    return 1;
  619. }
  620. #endif
  621.  
  622. #ifdef __CPLUSPLUS
  623. /*-----------------------------------------------------------------------*/
  624. static int near
  625. getheap(int flag)
  626. {
  627. struct heapinfo hp;
  628. int i = 0;
  629. #ifdef MDEBUG
  630. int j;
  631. #endif
  632.  
  633.    hp.ptr = 0;                          /* start at the beginning       */
  634.    while(1)   {
  635.           if (heapwalk(&hp) == _HEAPEND)
  636.                  break;
  637. #ifdef MDEBUG
  638.           if (flag == Over)   {
  639.                  for (j = 0; j < hp.size/16; j += 2)   {
  640.                         if (i == 0)
  641.                            tprintf("%04x ",FP_SEG(hp.ptr) + j);
  642.                         tputc(hp.in_use ? '+' : '-');
  643.                         if(++i == 72) {
  644.                            i = 0;
  645.                tputc('\n');
  646.                         }
  647.                  }
  648.           } else
  649. #endif
  650.           if (hp.in_use == flag) {
  651.                  tprintf("%4x %5lu",FP_SEG(hp.ptr),hp.size);
  652.                  if(++i == 6) {
  653.                         i = 0;
  654.                         tputc('\n');
  655.                  } else
  656.                         tputs(" | ");
  657.           }
  658.    }
  659.    tputs("\nEnd of list\n");
  660.    return 0;
  661. }
  662. #endif
  663.  
  664.  
  665.  
  666.  
  667. /* ------------------------ Memory subcmds ---------------------------- */
  668.  
  669.  
  670.  
  671.  
  672.  
  673. #ifdef MDEBUG
  674.  
  675. static char far *DumpAddr = NULL;           /* Memory dump pointer          */
  676.  
  677. /* called from config.c */
  678. int
  679. domdump(int argc,char *argv[],void *p)
  680. {
  681. unsigned int i;
  682. char *addr;
  683. unsigned int len = 8*16 ;                 /* default is 8 lines of hex dump*/
  684. /*
  685. Id *id;
  686. Hd *hd;
  687. */
  688. int seg;
  689.  
  690.    if((argc > 3 && DumpAddr == NULL) || (argc < 2 && DumpAddr == 0)) {
  691.           tputs("Usage: dump <segment|.> [decimal range]\n");
  692.       return 0;
  693.    }
  694.    if(argv[1][0] == '.' || argc == 1)
  695.       addr = DumpAddr;      /* Use last end address */
  696.    else
  697.       addr = (char *)(sltop(htol(argv[1])))-16;   /* get address of item being dumped */
  698.  
  699.    seg = FP_SEG(addr);
  700.  
  701.    if(argc == 3) {
  702.           len = atoi(argv[2]);
  703.       len = ((len + 15) >> 4) << 4;   /* round up to modulo 16 */
  704.    }
  705.  
  706.    if(len < 1) len = 1;
  707.    if(len > 256) len = 256;
  708.  
  709.    tprintf("Main Memory Dump Of Location %Fp\n"
  710.                    "Addr (offset)           Hexadecimal                         Ascii\n",
  711.                    addr);
  712.  
  713.    for(i = 0; i < len; i += 16)
  714.       fmtline((FILE *)0,seg++, (char *)(addr+i),16,0);
  715.    DumpAddr = MK_FP(seg,0);             /* update address               */
  716.    return 0;
  717. }
  718. #endif
  719.  
  720. static int
  721. docoldst(int argc,char *argv[],void *p)
  722. {
  723.         return setbool(&Memcold,"Reboot",argc,argv);
  724. }
  725.  
  726. #ifdef __CPLUSPLUS
  727. /*----------------------------------------------------------------------*
  728. * Print heap free list                                                  *
  729. *-----------------------------------------------------------------------*/
  730. static int
  731. dofreelist(int argc,char *argv[],void *p)
  732. {
  733.  
  734.    if (!_checkok())
  735.           return -1;
  736.  
  737.    return (getheap(Free));
  738. }
  739. #endif
  740.  
  741. static int
  742. doibufsize(int argc,char *argv[],void *p)
  743. {
  744.         return setuns(&Ibufsize,"Int buffer size",argc,argv);
  745. }
  746.  
  747. static int
  748. donibufs(int argc,char *argv[],void *p)
  749. {
  750.         return setint(&Nibufs,"Int pool buffers",argc,argv);
  751. }
  752.  
  753. #if((defined __CPLUSPLUS) && defined(MDDEBUG))
  754. static int
  755. doOverview(int argc,char *argv[],void *envp)
  756. {
  757.    if (!_checkok())
  758.       return -1;
  759.  
  760.    return (getheap(Over));
  761. }
  762. #endif
  763.  
  764. #ifdef MDEBUG
  765. static int
  766. dorecord(int argc,char **argv,void *p)
  767. {
  768.  
  769.    if (argc < 2)   {
  770.           tprintf("Memory recording %s\n", rfp ? "on" : "off");
  771.           return(0);
  772.    }
  773.  
  774.    if (!stricmp(argv[1],"off"))   {
  775.           if (rflag) {
  776.                  fclose(rfp);
  777.                  rflag=0;
  778.       }
  779.       return(0);
  780.    }
  781.  
  782.    if (rfp)   {
  783.        fclose (rfp);
  784.            rflag=0;
  785.    }
  786.    openmemrec(argv[1]);
  787.    return(0);
  788. }
  789. #endif
  790.  
  791. #ifdef MDEBUG
  792. static int
  793. dosizes(int argc,char *argv[],void *p)
  794. {
  795. int i;
  796.  
  797.    for(i = 0; i < 16; i += 4) {
  798.       tprintf("N>=%5u:%7ld| N>=%5u:%7ld| N>=%5u:%7ld| N>=%5u:%7ld\n",
  799.       1<<i,Sizes[i], 2<<i,Sizes[i+1],
  800.       4<<i,Sizes[i+2],8<<i,Sizes[i+3]);
  801.    }
  802.    return 0;
  803. }
  804. #endif
  805.  
  806. #ifdef MDEBUG
  807. static int
  808. dosnap(int argc,char **argv,void *p)
  809. {
  810. Hd cret;
  811.  
  812.    memset(&cret,0,sizeof(Hd));
  813.    strcpy(cret.file,"SnapDump");
  814.    if (!dump(&cret))
  815.           tputs("Dump successfully written...\n");
  816.    else
  817.           tputs("Can't open Dumpfile...\n");
  818.    return 0;
  819. }
  820. #endif
  821.  
  822. /*----------------------------------------------------------------------*
  823. * Print heap stats                                                      *
  824. *-----------------------------------------------------------------------*/
  825. static int
  826. dostat(int argc,char *argv[],void *envp)
  827. {
  828. extern int Intqlen, Iminfree;
  829. extern unsigned Ibufsize;
  830. extern long Ibuffail;
  831.  
  832.    tprintf("coreleft %lu",availmem());
  833.    tprintf("\nallocs %lu frees %lu diff %lu invalid allocs %lu frees %lu corrupted %lu\n",
  834.                         Allocs,Frees,Allocs-Frees,Memfail,Invalid,Overuse);
  835.    tprintf("int-off calls to malloc %lu free %lu\n"
  836.                    "Intqlen %u Ibufsize %u Iminfree %u Ibuffail %lu\n",
  837.                         Intalloc,Intfree,Intqlen,Ibufsize,Iminfree,Ibuffail);
  838.    return 0;
  839. }
  840.  
  841. static int
  842. dothresh(int argc,char *argv[],void *p)
  843. {
  844.         return setlong(&Memthresh,"Mem threshold (bytes)",argc,argv);
  845. }
  846.  
  847. #if((defined __CPLUSPLUS) && defined(MDDEBUG))
  848. /*----------------------------------------------------------------------*
  849. * Print heap used list                                                  *
  850. *-----------------------------------------------------------------------*/
  851. static int
  852. dousedlist(int argc,char *argv[],void *p)
  853. {
  854.    if (!_checkok())
  855.       return -1;
  856.  
  857.    return (getheap(Used));
  858. }
  859.  
  860. #endif
  861.  
  862. extern int dorefiq __ARGS((int argc,char *argv[],void *p));
  863.  
  864. /* ------------------------ Memory subcmd-parser ------------------------- */
  865. int
  866. domem(int argc,char *argv[],void *p)
  867. {
  868.         struct cmds Memcmds[] = {
  869. #ifdef __CPLUSPLUS
  870.            "freelist",     dofreelist,     0, 0, NULLCHAR,
  871. #endif
  872.            "ibufsize",     doibufsize,     0, 0, NULLCHAR,
  873.            "nibufs",       donibufs,       0, 0, NULLCHAR,
  874. #if((defined __CPLUSPLUS) && defined(MDDEBUG))
  875.            "overview",     doOverview,     0, 0, NULLCHAR,
  876. #endif
  877.            "reboot",       docoldst,       0, 0, NULLCHAR,
  878. #ifdef MDEBUG
  879.            "record",       dorecord,       0, 0, NULLCHAR,
  880. #endif
  881.            "refiq",                dorefiq,                0, 0, NULLCHAR,
  882. #ifdef MDEBUG
  883.            "sizes",        dosizes,        0, 0, NULLCHAR,
  884.            "snap",         dosnap,         0, 2, "snap start",
  885. #endif
  886.            "status",       dostat,         0, 0, NULLCHAR,
  887.            "thresh",       dothresh,       0, 0, NULLCHAR,
  888. #if((defined __CPLUSPLUS) && defined(MDDEBUG))
  889.            "usedlist",     dousedlist,     0, 0, NULLCHAR,
  890. #endif
  891.            NULLCHAR,
  892.         };
  893.  
  894.    return subcmd(Memcmds,argc,argv,p);
  895. }
  896.  
  897.  
  898.  
  899.